package com.luhuiguo.contacts.client.presenter;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasValue;
import com.google.inject.Inject;
import com.luhuiguo.contacts.client.AppConstants;
import com.luhuiguo.contacts.client.AppMessages;
import com.luhuiguo.contacts.client.AsyncCallbackWithStatus;
import com.luhuiguo.contacts.client.ui.Info;
import com.luhuiguo.contacts.shared.entity.Contact;
import com.luhuiguo.contacts.shared.event.ContactUpdatedEvent;
import com.luhuiguo.contacts.shared.event.ContactUpdatedEventHandler;
import com.luhuiguo.contacts.shared.event.EditContactCancelledEvent;
import com.luhuiguo.contacts.shared.event.EditContactCancelledEventHandler;
import com.luhuiguo.contacts.shared.rpc.CreateContact;
import com.luhuiguo.contacts.shared.rpc.CreateContactResult;
import com.luhuiguo.gwt.dispatcher.client.DispatcherAsync;
import com.luhuiguo.gwt.presenter.client.EventBus;
import com.luhuiguo.gwt.presenter.client.widget.WidgetDisplay;
import com.luhuiguo.gwt.presenter.client.widget.WidgetPresenter;
import com.luhuiguo.gwt.validation.client.ValidationException;
import com.luhuiguo.gwt.validation.client.ValidationProcessor;

public class EditContactPresenter extends WidgetPresenter<EditContactPresenter.Display> {

    public interface Display extends WidgetDisplay {

        HasClickHandlers getSubmit();

        HasClickHandlers getCancel();

        HasValue<String> getName();

        HasValue<String> getPhone();

        HasValue<String> getCompany();

        HasValue<String> getNote();

        void show();

        void center();
        
        void hide();

        ValidationProcessor getValidator();

        boolean validate();

        void setLoading(boolean loading);

    }

    private DispatcherAsync dispatcher;

    private AppMessages messages;

    private AppConstants constants;

    @Inject
    public EditContactPresenter(Display display, EventBus eventBus, DispatcherAsync dispatcher, AppConstants constants,
            AppMessages messages) {
        super(display, eventBus);
        this.dispatcher = dispatcher;
        this.constants = constants;
        this.messages = messages;
        GWT.log("EditContactPresenter created");

    }

    @Override
    protected void onBind() {
        GWT.log("EditContactPresenter onBind");

        registerHandler(eventBus.addHandler(EditContactCancelledEvent.TYPE, new EditContactCancelledEventHandler() {

            @Override
            public void onEditContactCancelled(EditContactCancelledEvent event) {
                display.hide();
                doReset();
            }

        }));

        registerHandler(display.getCancel().addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                eventBus.fireEvent(new EditContactCancelledEvent());
            }
        }));

        registerHandler(eventBus.addHandler(ContactUpdatedEvent.TYPE, new ContactUpdatedEventHandler() {

            @Override
            public void onContactUpdated(ContactUpdatedEvent event) {
                Info.display(messages.contactCreated(event.getUpdatedContact().getCompany()));
                display.hide();
            }
        }));

        registerHandler(display.getSubmit().addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                if (display.validate()) {
                    doSubmit();
                }

            }
        }));

    }

    @Override
    public void revealDisplay() {
        super.revealDisplay();
        display.center();

    }

    @Override
    protected void onRevealDisplay() {
        GWT.log("EditContactPresenter onRevealDisplay");
    }

    @Override
    protected void onUnbind() {
        GWT.log("EditContactPresenter onUnbind");
    }

    private void doSubmit() {
        display.setLoading(true);
        Contact c = new Contact();
        c.setName(display.getName().getValue());
        c.setPhone(display.getPhone().getValue());
        c.setCompany(display.getCompany().getValue());
        c.setNote(display.getNote().getValue());

        dispatcher.execute(new CreateContact(c), new AsyncCallbackWithStatus<CreateContactResult>() {

            @Override
            public void onFailureInternal(Throwable caught) {
                display.setLoading(false);
                if (caught instanceof ValidationException) {
                    display.getValidator().processServerErrors((ValidationException) caught);
                } else {
                    GWT.log("An error occurred while creating contact", caught);
                    Window.alert(constants.errorOccurred());
                }
                // doReset();
            }

            @Override
            public void onSuccessInternal(CreateContactResult result) {
                display.setLoading(false);
                eventBus.fireEvent(new ContactUpdatedEvent(result.getContact()));
                doReset();
            }

        });
    }

    private void doReset() {
        display.getName().setValue("");
        display.getPhone().setValue("");
        display.getCompany().setValue("");
        display.getNote().setValue("");

        display.getValidator().reset();
    }

}
